package com.demo.juc.locks;


import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author: yaoshubin
 * @Date: 2023-07-16  15:40
 * @Description: 可重入锁：说的是同一个对象
 * <p>
 * 1）Synchronied 隐式锁，同步代码块 + 同步方法
 * 又且仅有一个线程打印
 * Synchronied 可重入原理：MonitorObject 中的技术器，当线程持有锁的时候 ，monitorenter 计数器+1 ，monitorexit 计数器-1。计数器为0 代表锁释放
 * <p>
 *
 * 2）ReentrantLock 显式可重入，
 * 注意：
 * （1）lock() 和 unlock() 成对出现 ；
 * （2）finally{} 记得释放锁，否则会造成阻塞和死锁
 */
public class ReEntryLock {


    Object obj = new Object();

    // Synchronied 同步代码块
    public void m() {
        synchronized (obj) {
            System.out.println(Thread.currentThread().getName() + " 外层 synchronized block come in...");
            synchronized (obj) {
                System.out.println(Thread.currentThread().getName() + " 中层 synchronized block come in...");
                synchronized (obj) {
                    System.out.println(Thread.currentThread().getName() + " 内层 synchronized block come in...");
                }
            }
        }
    }


    //同步方法
    public synchronized void m1() {
        System.out.println(Thread.currentThread().getName() + " come in。。。");
        m2();
    }

    public synchronized void m2() {
        System.out.println(Thread.currentThread().getName() + " come in。。。");
        m3();
    }

    public synchronized void m3() {
        System.out.println(Thread.currentThread().getName() + " come in。。。");
    }


    public static void main(String[] args) {
        //验证Synchronied同步代码块
        ReEntryLock reEntryLock = new ReEntryLock();
        //reEntryLock.m();


        //验证Synchronied同步方法
        //reEntryLock.m1();

        ReentrantLock lock = new ReentrantLock();


        //ReentrantLock 显式可重入，注意：（1）lock() 和 unlock() 成对出现 ；（2）finally{} 记得释放锁，否则会造成阻塞和死锁
        new Thread(() -> {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + " 外层 come in...");
                lock.lock();
                try {
                    System.out.println(Thread.currentThread().getName() + " 中层 come in...");
                } finally {
                    lock.unlock();
                }
            } finally {
                //lock.unlock();   //若这行注释掉B无发获取锁造成阻塞
            }
        }, "A").start();


        /*new Thread(() -> {
            lock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + " come in...");
            } finally {
                lock.unlock();
            }
        }, "B").start();*/


    }
}
